package jaux.tank.utils.factory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import jaux.tank.utils.StringUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * Created  on 2018/3/22 0022.
 * 
 */
@Setter
@Getter
@Accessors(chain = true)
public class Page<T> {
	
	
	public static final int DEFAULT_PAGE_NO = 1;
	public static final int DEFAULT_PAGE_SIZE = 20;
	/**
     * 该操作只是为了忽略RowBounds属性
     *
     *
     */
    private int offset;
    /**
     * 该操作只是为了忽略RowBounds属性
     *
     *
     */
    private int limit;

    /**
     * 总数
     */
    private long total;

    /**
     * 每页显示条数，默认 20
     */
    private int size = DEFAULT_PAGE_SIZE;

    /**
     * 总页数
     */
    private int pages;

    /**
     * 当前页
     */
    private int current = DEFAULT_PAGE_NO;

    /**
     * 查询总记录数（默认 true）
     */
    private  boolean searchCount = true;

    /**
     * 开启排序（默认 true） 只在代码逻辑判断 并不截取sql分析
     *
     *
     **/
    private  boolean openSort = true;


    /**
     * <p>
     * SQL 排序 ASC 集合
     * </p>
     */
    private  List<String> ascs;
    /**
     * <p>
     * SQL 排序 DESC 集合
     * </p>
     */
    private  List<String> descs;

    /**
     * 是否为升序 ASC（ 默认： true ）
     *
     * @see #ascs
     * @see #descs
     */
    private  boolean isAsc = true;

    /**
     * <p>
     * SQL 排序 ORDER BY 字段，例如： id DESC（根据id倒序查询）
     * </p>
     * <p>
     * DESC 表示按倒序排序(即：从大到小排序)<br>
     * ASC 表示按正序排序(即：从小到大排序)
     *
     * @see #ascs
     * @see #descs
     * </p>
     */
    private  String orderByField;
    

    /**
     * 查询数据列表
     */
    private   List<T> records = Collections.emptyList();

    /**
     * 查询参数
     */
    private  Map<String, Object> condition;

    public Page() {

    }

    public Page(int current, int size, String orderByField) {

    	this(current, size);
        this.setOrderByField(orderByField);
    }

    public Page(int current, int size, String orderByField, boolean isAsc) {
        this(current, size, orderByField);
        this.setAsc(isAsc);
    }

    /**
     * <p>
     * 分页构造函数
     * </p>
     *
     * @param current 当前页
     * @param size    每页显示条数
     */
    public Page(int current, int size) {
        this(current,size,true);
    }

    public Page(int current, int size, boolean searchCount) {
        this(current, size, searchCount, true);
    }

    public Page(int current, int size, boolean searchCount, boolean openSort) {

        setOffset(offsetCurrent(current, size));
        setLimit(size);
        if (current > 1) {
            this.current = current;
        }
        this.size = size;
        this.searchCount = searchCount;
        this.openSort = openSort;
    }

    protected static int offsetCurrent(int current, int size) {
        if (current > 0) {
            return (current - 1) * size;
        }
        return 0;
    }

    public int offsetCurrent() {
        return offsetCurrent(this.current, this.size);
    }

    public boolean hasPrevious() {
        return this.current > 1;
    }

    public boolean hasNext() {
        return this.current < this.pages;
    }



    public int getPages() {
        if (this.size == 0) {
            return 0;
        }
        this.pages = (int) (this.total / this.size);
        if (this.total % this.size != 0) {
            this.pages++;
        }
        return this.pages;
    }


    


    private List<String> orders(boolean condition, List<String> columns) {
        if (!condition || StringUtils.isNotEmpty(orderByField)) {
        	return columns;
        }
        List<String> orders = new ArrayList<>();
        if (columns != null) {
        	orders.addAll(columns);
        }
        Arrays.asList(orderByField.split(",")).forEach(field -> {
            
        	if (!orders.contains(field)) {
        		orders.add(field);
        	}
        });
        return orders;
    }




    /**
     * @see #ascs
     * @see #descs
     * @deprecated
     */
    @Deprecated
    public boolean isAsc() {
    	return isAsc;
    }
    
    /**
     * @see #ascs
     * @see #descs
     * @deprecated
     */
    @Deprecated
    public Page<T> setAsc(boolean isAsc) {
    	this.isAsc = isAsc;
    	return this;
    }
    
    /**
     * @see #ascs
     * @see #descs
     */
    @Deprecated
    public String getOrderByField() {
        return orderByField;
    }

    /**
     * @see #ascs
     * @see #descs
     */
    @Deprecated
    public Page<T> setOrderByField(String orderByField) {
        if (StringUtils.isNotEmpty(orderByField)) {
            this.orderByField = orderByField;
            if(this.isAsc) {
            	this.ascs = orders(true, this.ascs);
            }else {
            	this.descs = orders(true, this.descs);
            }
        }
        return this;
    }

    @Override
    public String toString() {
        StringBuilder pg = new StringBuilder();
        pg.append(" Page:{ [").append(super.toString()).append("], ");
        if (records != null) {
            pg.append("records-size:").append(records.size());
        } else {
            pg.append("records is null");
        }
        return pg.append(" }").toString();
    }

}
